# -*- coding: utf-8 -*-

from mongoengine import *
from datetime import datetime
import hashlib

'''
## 城市/教学点/中控机/考勤机 （记录表）
{
    "_id" : ObjectId("5578ea8292ba6579599f4ba3"),
    "city" : "北京",
    "zipcode" : "010",
    "venues" : [ 
        {
            "name" : "和盛大厦",
            "id" : "ff8080814b4684a9014b483e6300043c",
            "disabled" : false,
            "ctm_devs" : [
                {"devid" : "pc483e6300043c1"},
                {"devid" : "pc483e6300043c2"}
            ],
            "card_readers" : [
                {"ip" : "192.168.13.101"},
                {"ip" : "192.168.13.102"}
            ]
        }, 
    ]
}

## 考勤服务器考勤日志
{
    "city" : "北京",
    "status" : True,    ## on_off
    "class_date" : 2015-06-11T17:23:37.981Z
    "attend_num" : 256
}
{
    "city" : "北京",
    "status" : True,    ## on_off
    "class_date" : 2015-06-11T17:23:37.981Z
    "attend_num" : 3
}

## 教学点中控机考勤日志
{
    "city" : 北京,
    "venue" : 和盛大厦,
    "ctm" : 49123001293,
    "status" : True,
    cpu : 8,
    memory : 40,
    disk : 50,
    app_live : True,
    app_ver : V1.0.0,
    database : True,
    port_9100 : True,
    port_3306 : True,
    crstatus : [
                {"ip" : "192.168.13.101", "status" : true },
                {"ip" : "192.168.13.102", "status" : true }
            ],
    "class_date" : 2015-06-11T17:39:37.493Z,
    "attend_num" : 256
}
终端设备监控：
1、CPU、内存和硬盘使用率，3306 9100 端口号
2、统计考勤表数据，数据表
3、应程序的版本号
4、教学点id 城市，设备名称

指令
事件同步指令

'''

'''
------------------------------------------------------------------------------
连接数据库
------------------------------------------------------------------------------
'''
def db_connect(dbname):
    connect(dbname)

'''
------------------------------------------------------------------------------
读卡器表
------------------------------------------------------------------------------
'''
class CardReader(EmbeddedDocument):
    ip = StringField(max_length=32, required=True)
    memo = StringField()

'''
------------------------------------------------------------------------------
读卡器状态表
------------------------------------------------------------------------------
'''
class CardReaderStatus(EmbeddedDocument):
    ip = StringField(max_length=32, required=True)
    status = BooleanField(default=False, required=True)

'''
------------------------------------------------------------------------------
电源设备表
------------------------------------------------------------------------------
'''
class PwrDevice(Document):
    devid = StringField(max_length=32, required=True, unique=True)
    ip = StringField(max_length=32, required=True)
    output = FloatField(default=0.0, required=True)
    dev_type = StringField(default="", max_length=32, required=True)
    memo = StringField()

'''
------------------------------------------------------------------------------
服务器表
------------------------------------------------------------------------------
'''
class SrvDevice(Document):
    devid = StringField(max_length=32, required=True, unique=True)
    ip = StringField(max_length=32, required=True)
    hostname = StringField(max_length=32, required=True)
    dev_type = StringField(default="", max_length=32, required=True)
    location = StringField(max_length=1024, required=True)
    memo = StringField()

'''
------------------------------------------------------------------------------
网络设备表
------------------------------------------------------------------------------
'''
class NetDevice(Document):
    devid = StringField(max_length=32, required=True, unique=True)
    ip = StringField(max_length=32, required=True)
    port_nr = IntField(default=0, required=True)
    dev_type = StringField(default="", max_length=32, required=True)
    location = StringField(max_length=1024, required=True)
    memo = StringField()

'''
------------------------------------------------------------------------------
移动设备表
------------------------------------------------------------------------------
'''
class MdmDevice(Document):
    devid = StringField(max_length=32, required=True, unique=True)
    ip = StringField(max_length=32, required=True)
    mac = StringField(max_length=32, required=True)
    dev_type = StringField(default="", max_length=32, required=True)
    memo = StringField()

'''
------------------------------------------------------------------------------
班级表
------------------------------------------------------------------------------
'''
class ClassRoom(Document):
    roomid = StringField(max_length=32, required=True, unique=True)
    location = StringField(max_length=1024, required=True)
    memo = StringField()
    mdm_devs = ListField(ReferenceField(MdmDevice))

'''
------------------------------------------------------------------------------
中控机表
------------------------------------------------------------------------------
'''
class CtmDevice(Document):
    devid = StringField(max_length=32, required=True, unique=True)
    memo = StringField()

'''
------------------------------------------------------------------------------
教学点表
------------------------------------------------------------------------------
'''
class Venue(Document):
    name = StringField(max_length=32, required=True)
    venue_id = StringField(max_length=32, required=True, unique=True)
    disabled = BooleanField(default=False, required=True)
    service_name = StringField(max_length=32)
    memo = StringField()
    power_devs = ListField(ReferenceField(PwrDevice))
    server_devs = ListField(ReferenceField(SrvDevice))
    network_devs = ListField(ReferenceField(NetDevice))
    mdm_devs = ListField(ReferenceField(MdmDevice))
    ctm_devs = ListField(ReferenceField(CtmDevice))
    card_readers = ListField(EmbeddedDocumentField('CardReader'))
    classroom_list = ListField(ReferenceField(ClassRoom))

'''
------------------------------------------------------------------------------
教学点组表（合并教学点)
------------------------------------------------------------------------------
'''
class VenueGroup(Document):
    venues = ListField(ReferenceField(Venue))

'''
------------------------------------------------------------------------------
城市表
------------------------------------------------------------------------------
'''
class City(Document):
    name = StringField(max_length=32, required=True, unique=True)
    zipcode = StringField(max_length=8, required=True, unique=True)
    venues = ListField(ReferenceField(Venue))
    venuegroups = ListField(ReferenceField(VenueGroup))

'''
------------------------------------------------------------------------------
电子考勤服务器监控日志
------------------------------------------------------------------------------
'''
class AcardCityLog(Document):
    city = ReferenceField(City, required=True)
    status = BooleanField(default=False, required=True)
    class_date = DateTimeField(required=True)
    attend_num = IntField(default=0, required=True)
    log_tm = DateTimeField(default=datetime.now(), required=True)

'''
------------------------------------------------------------------------------
中控机监控日志
------------------------------------------------------------------------------
'''
class AcardCtmLog(Document):
    city = ReferenceField(City, required=True)
    venue = ReferenceField(Venue, required=True)
    ctm = ReferenceField(CtmDevice, required=True)
    status = BooleanField(default=False, required=True)
    cpu = FloatField(default=0.0, required=True)
    memory = FloatField(default=0.0, required=True)
    disk = FloatField(default=0.0, required=True)
    app_live = BooleanField(default=False, required=True)
    app_ver = StringField(default="0.0", max_length=32, required=True)
    cli_ver = StringField(default="0.0", max_length=8, required=True)
    port_9100 = BooleanField(default=False, required=True)
    port_3306 = BooleanField(default=False, required=True)
    master_slaver = BooleanField(default=False)
    ip_100 = BooleanField(default=False, required=True)
    crstatus = ListField(EmbeddedDocumentField('CardReaderStatus'))
    class_date = DateTimeField(default=datetime(1970,1,1), required=True)
    ctm_date = StringField(default="1970-1-1", required=True)
    attend_num = IntField(default=0, required=True)
    attend = IntField(default=0)
    noattend = IntField(default=0)
    toattend = IntField(default=0)
    log_tm = DateTimeField(default=datetime.now(), required=True)

'''
------------------------------------------------------------------------------
电子考勤每日刷卡量日志
------------------------------------------------------------------------------
'''
class AttendTurnoutLog(Document):
    city = ReferenceField(City, required=True)
    venue = ReferenceField(Venue, required=True)
    ctm = ReferenceField(CtmDevice, required=True)
    date = DateTimeField(required=True)
    attend = IntField(required=True)
    noattend = IntField(required=True)
    toattend = IntField(required=True)
'''
------------------------------------------------------------------------------
TDM用户表
------------------------------------------------------------------------------
'''
class TdmUser(Document):
    name = StringField(max_length=32, required=True, unique=True)
    passwd_md5 = StringField(max_length=32, required=True)
    email = EmailField(required=True)
    phone = StringField()
    create_tm = DateTimeField(default=datetime.now(), required=True)
    lastlogin_tm = DateTimeField(default=datetime.now(), required=True)
    grant = StringField(choices =["admin", "view"], required=True)
    station = ListField(ReferenceField(City))

'''
------------------------------------------------------------------------------
TDM模块表
------------------------------------------------------------------------------
'''
class TdmModule(Document):
    name = StringField(max_length=32, required=True, unique=True)
    alias = StringField(max_length=32, required=True, unique=True)
    alert_enable = BooleanField(default=False, required=True)
    alert_by_city = BooleanField(default=False, required=True)
    officers = ListField(ReferenceField(TdmUser))

'''
------------------------------------------------------------------------------
TDM告警表
------------------------------------------------------------------------------
'''
class TdmAlert(Document):
    alert_mail_user = EmailField(required=True)
    alert_mail_pass = StringField(max_length=32, required=True)
    alert_mail_items = ListField(ReferenceField(TdmModule))

'''
------------------------------------------------------------------------------
TDM日志表
------------------------------------------------------------------------------
'''
class TdmLog(Document):
    tm = DateTimeField(default=datetime.now(), required=True)
    module = ReferenceField(TdmModule, required=True)
    city = ReferenceField(City, required=True)
    venue = ReferenceField(Venue, required=True)
    dev = StringField()
    item = StringField()
    content = StringField()

'''
------------------------------------------------------------------------------
[初始化] 城市教学点数据库初始化
------------------------------------------------------------------------------
'''
def tdm_mongo_city_venue_init():
    db_connect('attend')
    city_venue_list = open('acard_city_venue.txt').read().split('\n')
    #杭州,0571,西湖大厦,ff8080812fc298b5012fd3ba9f310da9
    for cv in city_venue_list:
        if not cv:
            continue
        city_name, zipcode, venue_name, venue_id = cv.split(',')

        # add venue
        venue = Venue.objects(venue_id=venue_id).first()
        if not venue:
            venue = Venue(name=venue_name, venue_id=venue_id, disabled=False, ctm_devs=[], card_readers=[])
            venue.save()
            print 'new venue:[%s]' % (venue.name,)

        city = City.objects(zipcode=zipcode).first()
        if not city:
            city = City(name=city_name, zipcode=zipcode, venues=[venue])
            city.save()
            print 'new city:[%s]' % (city.name,)
        else:
            #print city.venues
            if not venue in city.venues:
                city.venues.append(venue)
                city.save()
                print 'add venue [%s] to city [%s]' % (venue.name, city.name)

'''
------------------------------------------------------------------------------
[初始化] 用户数据库初始化
------------------------------------------------------------------------------
'''
def tdm_mongo_user_init():
    db_connect('attend')
    def_users = [
        ('admin', 'abc@1234', 'qujianning@100tal.com', 'admin'),
        ('chenzhan', 'abc@1234', 'chenzhan@100tal.com', 'admin'),
        ('lijianfei', 'abc@1234', 'duojie@100tal.com', 'admin'),
        ('zhangyuanyuan', 'abc@1234', 'zhangyuanyuan@100tal.com', 'admin'),
        ('test', 'abc@1234', 'test@100tal.com', 'view')
    ]
    # delete the collection
    TdmUser.drop_collection()
    # add default data
    for uname, upass, umail, ugrant in def_users:
        u1 = TdmUser.objects(name=uname).first()
        if not u1:
            u1 = TdmUser(name=uname, passwd_md5=hashlib.md5(upass).hexdigest(), email=umail, grant=ugrant)
            u1.save()
            print 'add new user %s[%s] %s' % (uname, ugrant, umail)

'''
------------------------------------------------------------------------------
[初始化] 模块告警数据库初始化
------------------------------------------------------------------------------
'''
def tdm_mongo_module_alert_init():
    db_connect('attend')
    def_modules = [
        ('power', '电源', False, False, []),
        ('network', '网络', False, False, []),
        ('server', '服务器', False, False, []),
        ('mdm', '移动设备', False, False, []),
        ('acard', '电子听课证', False, False, [])
    ]
    # delete the collection
    TdmModule.drop_collection()
    # add default data
    for name, alias, enable, by_city, officers in def_modules:
        m1 = TdmModule.objects(name=name).first()
        if not m1:
            m1 = TdmModule(name=name, alias=alias, alert_enable=enable, alert_by_city=by_city, officers=officers)
            m1.save()
            print 'add new module %s[%s] %s,%s' % (alias, name, enable, by_city)

    def_alert_mail_user, def_alert_mail_pass = ('cxyf@100tal.com', 'icstest123')
    a1 = TdmAlert(alert_mail_user = def_alert_mail_user, alert_mail_pass = def_alert_mail_pass)
    for mod in TdmModule.objects():
        a1.alert_mail_items.append(mod)
    a1.save()

if __name__ == "__main__":
    tdm_mongo_user_init()
    tdm_mongo_module_alert_init()
